use honeybee::mongodb::{
    bson::{self, doc},
    options::FindOneAndUpdateOptions,
};
use honeybee::Result;
use serde::{Deserialize, Serialize};

use super::collections;

#[derive(Serialize, Deserialize, Debug)]
struct Uid {
    next_id: i64,
}

pub async fn init(init_uid: i64) -> Result<()> {
    let coll = collections::uid();
    if coll.find_one(None, None).await?.is_none() {
        info!("init id_allocator collections");
        let uid = Uid { next_id: init_uid };

        let doc = bson::to_document(&uid)?;
        coll.insert_one(doc, None).await?;
    }
    Ok(())
}

pub async fn inc_update(count: i64) -> Result<i64> {
    let coll = collections::uid();
    let option = FindOneAndUpdateOptions::builder()
        .projection(Some(doc! {"_id": false}))
        .build();
    let start_uid = coll
        .find_one_and_update(
            doc! {},
            doc! {"$inc": {
                "next_id": count,
            }},
            option,
        )
        .await?
        .ok_or_else(|| anyhow!("find_one_and_update return None"))?;
    Ok(start_uid.get_i64("next_id")?)
}
